Completed
Push — master ( 6ebb3a...bbab3f )
by Johan
11s
created

UPCE.js ➔ expandToUPCA

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 18
1
// Encoding documentation:
2
// https://en.wikipedia.org/wiki/Universal_Product_Code#Encoding
3
//
4
// UPC-E documentation:
5
// https://en.wikipedia.org/wiki/Universal_Product_Code#UPC-E
6
7
import EANencoder from './ean_encoder.js';
8
import Barcode from "../Barcode.js";
9
import { checksum } from './UPC.js';
10
11
const EXPANSIONS = [
12
	"XX00000XXX",
13
	"XX10000XXX",
14
	"XX20000XXX",
15
	"XXX00000XX",
16
	"XXXX00000X",
17
	"XXXXX00005",
18
	"XXXXX00006",
19
	"XXXXX00007",
20
	"XXXXX00008",
21
	"XXXXX00009"
22
];
23
24
const PARITIES = [
25
	["EEEOOO", "OOOEEE"],
26
	["EEOEOO", "OOEOEE"],
27
	["EEOOEO", "OOEEOE"],
28
	["EEOOOE", "OOEEEO"],
29
	["EOEEOO", "OEOOEE"],
30
	["EOOEEO", "OEEOOE"],
31
	["EOOOEE", "OEEEOO"],
32
	["EOEOEO", "OEOEOE"],
33
	["EOEOOE", "OEOEEO"],
34
	["EOOEOE", "OEEOEO"]
35
];
36
37
class UPCE extends Barcode{
38
	constructor(data, options){
39
		// Code may be 6 or 8 digits;
40
		// A 7 digit code is ambiguous as to whether the extra digit
41
		// is a UPC-A check or number system digit.
42
		super(data, options);
43
		this.isValid = false;
44
		if(data.search(/^[0-9]{6}$/) !== -1){
45
			this.middleDigits = data;
46
			this.upcA = expandToUPCA(data, "0");
47
			this.text = options.text ||
48
				`${this.upcA[0]}${data}${this.upcA[this.upcA.length - 1]}`;
49
			this.isValid = true;
50
		}
51
		else if(data.search(/^[01][0-9]{7}$/) !== -1){
52
			this.middleDigits = data.substring(1, data.length - 1);
53
			this.upcA = expandToUPCA(this.middleDigits, data[0]);
54
55
			if(this.upcA[this.upcA.length - 1] === data[data.length - 1]){
56
				this.isValid = true;
57
			}
58
			else{
59
				// checksum mismatch
60
				return;
61
			}
62
		}
63
		else{
64
			return;
65
		}
66
67
		this.displayValue = options.displayValue;
68
69
		// Make sure the font is not bigger than the space between the guard bars
70
		if(options.fontSize > options.width * 10){
71
			this.fontSize = options.width * 10;
72
		}
73
		else{
74
			this.fontSize = options.fontSize;
75
		}
76
77
		// Make the guard bars go down half the way of the text
78
		this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
79
	}
80
81
	valid(){
82
		return this.isValid;
83
	}
84
85
	encode(){
86
		if(this.options.flat){
87
			return this.flatEncoding();
88
		}
89
		else{
90
			return this.guardedEncoding();
91
		}
92
	}
93
94
	flatEncoding(){
95
		var encoder = new EANencoder();
96
		var result = "";
97
98
		result += "101";
99
		result += this.encodeMiddleDigits(encoder);
100
		result += "010101";
101
102
		return {
103
			data: result,
104
			text: this.text
105
		};
106
	}
107
108
	guardedEncoding(){
109
		var encoder = new EANencoder();
110
		var result = [];
111
112
		// Add the UPC-A number system digit beneath the quiet zone
113
		if(this.displayValue){
114
			result.push({
115
				data: "00000000",
116
				text: this.text[0],
117
				options: {textAlign: "left", fontSize: this.fontSize}
118
			});
119
		}
120
121
		// Add the guard bars
122
		result.push({
123
			data: "101",
124
			options: {height: this.guardHeight}
125
		});
126
127
		// Add the 6 UPC-E digits
128
		result.push({
129
			data: this.encodeMiddleDigits(encoder),
130
			text: this.text.substring(1, 7),
131
			options: {fontSize: this.fontSize}
132
		});
133
134
		// Add the end bits
135
		result.push({
136
			data: "010101",
137
			options: {height: this.guardHeight}
138
		});
139
140
		// Add the UPC-A check digit beneath the quiet zone
141
		if(this.displayValue){
142
			result.push({
143
				data: "00000000",
144
				text: this.text[7],
145
				options: {textAlign: "right", fontSize: this.fontSize}
146
			});
147
		}
148
149
		return result;
150
	}
151
152
	encodeMiddleDigits(encoder) {
153
		const numberSystem = this.upcA[0];
154
		const checkDigit = this.upcA[this.upcA.length - 1];
155
		const parity = PARITIES[parseInt(checkDigit)][parseInt(numberSystem)];
156
		return encoder.encode(this.middleDigits, parity);
157
	}
158
}
159
160
function expandToUPCA(middleDigits, numberSystem) {
161
	const lastUpcE = parseInt(middleDigits[middleDigits.length - 1]);
162
	const expansion = EXPANSIONS[lastUpcE];
163
164
	let result = "";
165
	let digitIndex = 0;
166
	for(let i = 0; i < expansion.length; i++) {
167
		let c = expansion[i];
168
		if (c === 'X') {
169
			result += middleDigits[digitIndex++];
170
		} else {
171
			result += c;
172
		}
173
	}
174
175
	result = `${numberSystem}${result}`;
176
	return `${result}${checksum(result)}`;
177
}
178
179
export default UPCE;
180